use askama_axum::{IntoResponse, Template};
use axum::extract::{Path, Query, State};
use axum::response::Redirect;
use axum::Form;
use tower_cookies::Cookies;
use tower_sessions::Session;

use crate::controllers::backend::ErrorTemplate;
use crate::core::xerror::{GLOBALERROR, XErrors};
use crate::core::AppState;
use crate::services::backend::advert_position_service::AdvertPositionService;
use crate::services::backend::advert_service::AdvertService;
use crate::types::common::Breadcrumb;
use crate::types::backend::advert_type::{AdvertListReq, AdvertRow, AdvertForm};
use crate::types::common::OptionRow;

use super::AdminSession;


#[derive(Template)]
#[template(path = "backend/advert/list.html")]
struct AdvertListTemplate {
    auth: AdminSession,
    breadcrumb: Breadcrumb,
    paginate: String,
    list: Vec<AdvertRow>,
    advert_positions: Vec<OptionRow>
}

#[derive(Template)]
#[template(path = "backend/advert/form.html")]
struct AdvertFormTemplate {
    auth: AdminSession,
    breadcrumb: Breadcrumb,
    data: AdvertForm,
    url: String,
    advert_positions: Vec<OptionRow>
}

/// 获取广告分页列表
pub async fn adverts_handler(State(state): State<AppState>, session: Session, Query(args):Query<AdvertListReq>) -> impl IntoResponse {
    let auth = AdminSession::init(session).await;
    // 全部位置
    let advert_positions_res = AdvertPositionService::get_option_advert_positions(&state.db).await;
    let advert_positions = match advert_positions_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    let res = AdvertService::get_advert_page(&state.db, &args).await;
    let breadcrumb = Breadcrumb {
        title: "广告管理".to_string(),
        sub_title: "广告列表".to_string(),
    };

    match res {
        Ok(data) => {
            let template = AdvertListTemplate { 
                auth,
                breadcrumb,
                paginate: data.paginate, 
                list: data.list,
                advert_positions
            };
            return axum::response::Html(template.render().unwrap())
        },
        Err(e) => {
            print!("{}", e.to_string());
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    }
}

/// 添加广告表单
pub async fn add_advert_handler(State(state): State<AppState>, session: Session) -> impl IntoResponse {
    let auth = AdminSession::init(session).await;
    // 全部位置
    let advert_positions_res = AdvertPositionService::get_option_advert_positions(&state.db).await;
    let advert_positions = match advert_positions_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    let breadcrumb = Breadcrumb {
        title: "广告管理".to_string(),
        sub_title: "添加广告".to_string(),
    };
    let template = AdvertFormTemplate { 
        auth,
        breadcrumb,
        data: AdvertForm { 
            pid: 0, 
            name: "".to_string(), 
            url: "".to_string(), 
            image: "".to_string(),
            order_by: 0
        },
        url: "/backend/advert/create".to_string(),
        advert_positions
    };
    return axum::response::Html(template.render().unwrap());
}

/// 添加广告操作
pub async fn create_advert_handler(
    State(state): State<AppState>, 
    cookies: Cookies,
    Form(form): Form<AdvertForm>) -> Redirect {
    let error = XErrors::new();
    if form.name == "" || form.pid <= 0 {
        error.set_cookie_error(cookies, GLOBALERROR::PARAMINVALIDFAILED, "".to_string());
        return Redirect::to("/backend/advert/create")
    }
    
    let res = AdvertService::insert_advert(&state.db, &form).await;
    match res {
        Ok(_) => {
            error.set_cookie_error(cookies, GLOBALERROR::ADDSUCCESS, "".to_string());
            return Redirect::to("/backend/advert/list")
        }, 
        Err(e) => {
            let db_error = e.to_string();
            error.set_cookie_error(cookies, GLOBALERROR::ADDFAILED, db_error);
            return Redirect::to("/backend/advert/list")
        }
    }
}

/// 修改广告表单
pub async fn edit_advert_handler(State(state): State<AppState>, session: Session, Path(id): Path<i64>) -> impl IntoResponse {
    let auth = AdminSession::init(session).await;
    // 全部位置
    let advert_positions_res = AdvertPositionService::get_option_advert_positions(&state.db).await;
    let advert_positions = match advert_positions_res {
        Ok(data) => data,
        Err(e) => {
            let template = ErrorTemplate{
                msg: e.to_string()
            };
            return axum::response::Html(template.render().unwrap())
        }
    };

    let breadcrumb = Breadcrumb {
        title: "广告管理".to_string(),
        sub_title: "修改广告".to_string(),
    };

    let res = AdvertService::get_advert_by_id(&state.db, id).await;
    match res {
        Ok(data) => {
            let template = AdvertFormTemplate { 
                auth,
                breadcrumb,
                data,
                url: "/backend/advert/edit/".to_string() + &id.to_string(),
                advert_positions
             };
            return axum::response::Html(template.render().unwrap())
        },
        Err(e) => {
            let template = ErrorTemplate{ 
                msg: e.to_string(), 
            };
            return axum::response::Html(template.render().unwrap())
        }
    }
}

/// 修改广告操作
pub async fn update_advert_handler(
    State(state): State<AppState>, 
    cookies: Cookies,
    Path(id): Path<i64>, 
    Form(form): Form<AdvertForm>) -> Redirect {
    let error = XErrors::new();
    if form.name == "" || form.pid <= 0 {
        error.set_cookie_error(cookies, GLOBALERROR::PARAMINVALIDFAILED, "".to_string());
        return Redirect::to(format!("/backend/advert/edit/{}", id).as_str());
    }

    let res = AdvertService::update_advert(&state.db, id, &form).await;
    match res {
        Ok(_) => {
            error.set_cookie_error(cookies, GLOBALERROR::UPDATESUCCESS, "".to_string());
            return Redirect::to("/backend/advert/list")
        },
        Err(e) => {
            let db_error = e.to_string();
            error.set_cookie_error(cookies, GLOBALERROR::UPDATEFAILED, db_error);
            return Redirect::to("/backend/advert/list")
        }
    }
}

/// 删除广告操作
pub async fn delete_advert_handler(
    State(state): State<AppState>, 
    cookies: Cookies,
    Path(id): Path<i64>) -> Redirect {
    let error = XErrors::new();
    let exist = AdvertService::exist_advert_by_id(&state.db, id).await;
    let total = match exist {
        Ok(total) => total,
        Err(_) => 0,
    };
    if total == 0 {
        error.set_cookie_error(cookies, GLOBALERROR::RECORDNOTFOUND, "".to_string());
        return Redirect::to("/backend/advert/list");
    }

    let res = AdvertService::delete_advert(&state.db, id).await;
    match res {
        Ok(_) => {
            error.set_cookie_error(cookies, GLOBALERROR::DELETESUCCESS, "".to_string());
            return Redirect::to("/backend/advert/list")
        },
        Err(e) => {
            let db_error = e.to_string();
            error.set_cookie_error(cookies, GLOBALERROR::DELETEFAILED, db_error);
            return Redirect::to("/backend/advert/list")
        }
    }
}